/*
 * @Author: your name
 * @Date: 2021-09-21 14:33:27
 * @LastEditTime: 2021-09-23 22:43:16
 * @LastEditors: Please set LastEditors
 * @Description: In User Settings Edit
 * @FilePath: \threadpool\threadpool.h
 */
#include "threadpool.h"

using namespace hyf;

ThreadPool::ThreadPool(unsigned int size) : m_isRun(true)
{
    unsigned int uSize = size > maxNums ? maxNums : size;

    m_idlNum = uSize;
    AddThread(uSize);
}

ThreadPool::~ThreadPool()
{
    m_isRun = false;
    m_cv.notify_all();
    for (auto &thread : m_pool)
    {
        if (thread.joinable())
        {
            thread.join();
        }
    }
}

int ThreadPool::IdlCount() const
{
    return m_idlNum;
}

bool ThreadPool::IsRun() const
{
    return m_isRun;
}

void ThreadPool::AddThread(unsigned int num)
{
    for (; m_pool.size() < num && num >= 0;)
    {
        // 此lambda为线程初始化函数，也就是线程的执行流
        m_pool.emplace_back([this]
                            {
                                while (m_isRun)
                                {
                                    Task task;
                                    {
                                        std::unique_lock<std::mutex> locker(m_mutex);
                                        m_cv.wait(locker, [this]
                                                  { return !m_isRun || !m_tasks.empty(); }); // 1、m_isRun为true,其后续状态只取决于任务队列是为空； 2、m_isRun为false,即使任务队列为空，也不会继续阻塞，满足此条件是为了结束进程

                                        if (m_tasks.empty() && !m_isRun) // 根据左边状态进行线程结束状态判断
                                        {
                                            return;
                                        }
                                        task = std::move(m_tasks.front());
                                        m_tasks.pop();
                                    }
                                    m_idlNum--;
                                    task();
                                    m_idlNum++;
                                }
                            });
    }
}

void ThreadPool::push(const Task &task)
{
    {
        std::unique_lock<std::mutex> lock(m_mutex);
        m_tasks.emplace(task);
    }
    m_cv.notify_one();
}
